﻿/*-------------------------------------------------------------------------
* 命名空间: ScreenCapture.Base.Services/ServiceProvider
* 类       名: ServiceProvider
* 功      能:  TD
* 时      间:  2023/12/1 11:28:51
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using Ninject;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;

namespace ScreenCapture.Base.Services
{
    // 服务配置类,一些公共的设置
    public static class ServiceProvider
    {

        public const string ScreenCapturePathConstant = "%SCREENCAPTURE_PATH%";

        // 应用程序的根目录,这里不需要设置,所以是只读属性
        /*
         * 注意readonly只能用在字段上,不能用在属性上,属性本质上是方法,就是get和set方法.
         * 如果是只读属性就只提供get方法就行了.
         */
        public static string AppDir
        {
            get
            {
                // 获取当前应用程序的全路径,应用程序根目录+应用程序.exe,类似下面这种
                // C:\Program Files\MyApp\MyApp.exe
                var location = Assembly.GetExecutingAssembly().Location;
                return location == null ? "" : Path.GetDirectoryName(location);
            }
        }

        /// <summary>
        /// 项目的配置设置目录Settings目录
        /// </summary>
        private static string _settingsDir;

        public static string SettingsDir
        {
            get
            {
                if (_settingsDir == null)
                {
                    var localSetttings = Path.Combine(AppDir, "Settings");
                    if (Directory.Exists(localSetttings))
                    {
                        _settingsDir = localSetttings;
                    }
                    else
                    {
                        /*
                         * 如果App根目录下不存在Settings目录,就在唉AppDta\Roaming下根据项目名称创建一个文件夹用来保存信息.
                         * 本电脑获取的是固定目录: C:\Users\Fioman\AppData\Roaming
                         * 名称为项目名称+Info,这个用来代替根目录下的Settings目录,如果Settings目录已经存在就不再创建下面这个目录
                         * 使用nameof的目的就是防止项目名称发生变化,预防硬编码的问题
                         */
                        var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                        _settingsDir = Path.Combine(appDataPath, $"{nameof(ScreenCapture)}_Info");
                    }
                }

                if (!Directory.Exists(_settingsDir))
                {
                    Directory.CreateDirectory(_settingsDir);
                }
                return _settingsDir;
            }

            set
            {
                if (string.IsNullOrWhiteSpace(value))
                    return;

                value = value.Replace(ScreenCapturePathConstant, AppDir);

                _settingsDir = value;
                if (!Directory.Exists(_settingsDir))
                {
                    Directory.CreateDirectory(_settingsDir);
                }
            }
        }

        // 依赖注入绑定操作的Kernel类
        static IKernel Kernel { get; } = new StandardKernel();
        static readonly List<IModule> LoadedModules = new List<IModule>();

        // 依赖注入通过Ninject包来进行依赖注入管理
        // 模块加载,加载传入的模块,其实就是手动的调用了Niject的load方法.
        // 然后最后封装称了调用Module类中的OnLoad()方法
        public static void LoadModule(IModule Module)
        {
            Kernel.Load(new MyBinder(Module));
            LoadedModules.Add(Module);
        }

        // 获取一个服务接口注册的实际类的一个对象
        public static T Get<T>() => Kernel.Get<T>();

        /// <summary>
        ///  获取程序集的名称和版本信息的AssemblyName对象的 Version属性,这属性是一个Version对象.
        ///  Version对象包含了四个部分的版本号信息: 主版本号,次版本号,内部版本号和修订号. 例如:
        ///  1.2.3.4 主版本是1,次版本是2,内部版本3,修订版本号4
        /// </summary>
        public static Version AppVersion => Assembly.GetEntryAssembly()?.GetName().Version;
    }
}
